{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "iZNjG2KMmyDi"
   },
   "source": [
    "# 倒立摆 Pendulum-v0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "ocihf3XMmyDk"
   },
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "np.random.seed(0)\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt\n",
    "import gym\n",
    "import tensorflow.compat.v2 as tf\n",
    "tf.random.set_seed(0)\n",
    "from tensorflow import keras"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 环境"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 34
    },
    "colab_type": "code",
    "id": "E3nCy2ULmyDr",
    "outputId": "f403dcf0-01b2-41ac-cdfd-5fad13f61e0d"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0]"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "env = gym.make('Pendulum-v0')\n",
    "env.seed(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "colab_type": "text",
    "id": "iWFtkv0LmyDz"
   },
   "source": [
    "用深度确定性策略梯度算法求解"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "gxbw9KN3myD2"
   },
   "outputs": [],
   "source": [
    "class DQNReplayer:\n",
    "    def __init__(self, capacity):\n",
    "        self.memory = pd.DataFrame(index=range(capacity),\n",
    "                columns=['observation', 'action', 'reward',\n",
    "                'next_observation', 'done'])\n",
    "        self.i = 0\n",
    "        self.count = 0\n",
    "        self.capacity = capacity\n",
    "    \n",
    "    def store(self, *args):\n",
    "        self.memory.loc[self.i] = args\n",
    "        self.i = (self.i + 1) % self.capacity\n",
    "        self.count = min(self.count + 1, self.capacity)\n",
    "        \n",
    "    def sample(self, size):\n",
    "        indices = np.random.choice(self.count, size=size)\n",
    "        return (np.stack(self.memory.loc[indices, field]) for field in\n",
    "                self.memory.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "u4kWbfiUmyD6"
   },
   "outputs": [],
   "source": [
    "class OrnsteinUhlenbeckProcess:\n",
    "    def __init__(self, size, mu=0., sigma=1., theta=.15, dt=.01):\n",
    "        self.size = size\n",
    "        self.mu = mu\n",
    "        self.sigma = sigma\n",
    "        self.theta = theta\n",
    "        self.dt = dt\n",
    "        \n",
    "    def __call__(self):\n",
    "        n = np.random.normal(size=self.size)\n",
    "        self.x += (self.theta * (self.mu - self.x) * self.dt +\n",
    "                self.sigma * np.sqrt(self.dt) * n)\n",
    "        return self.x\n",
    "        \n",
    "    def reset(self, x=0.):\n",
    "        self.x = x * np.ones(self.size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "4BSNHGBimyD-"
   },
   "outputs": [],
   "source": [
    "class DDPGAgent:\n",
    "    def __init__(self, env, actor_kwargs, critic_kwargs,\n",
    "            replayer_capacity=100000, replayer_initial_transitions=10000,\n",
    "            gamma=0.99, batches=1, batch_size=64,\n",
    "            net_learning_rate=0.005, noise_scale=0.1, explore=True):\n",
    "        observation_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.shape[0]\n",
    "        observation_action_dim = observation_dim + action_dim\n",
    "        self.action_low = env.action_space.low\n",
    "        self.action_high = env.action_space.high\n",
    "        self.gamma = gamma\n",
    "        self.net_learning_rate = net_learning_rate\n",
    "        self.explore = explore\n",
    "        \n",
    "        self.batches = batches\n",
    "        self.batch_size = batch_size\n",
    "        self.replayer = DQNReplayer(replayer_capacity)\n",
    "        self.replayer_initial_transitions = replayer_initial_transitions\n",
    "        \n",
    "        self.noise = OrnsteinUhlenbeckProcess(size=(action_dim,),\n",
    "                sigma=noise_scale)\n",
    "        self.noise.reset()\n",
    "        \n",
    "        self.actor_evaluate_net = self.build_network(\n",
    "                input_size=observation_dim, **actor_kwargs)\n",
    "        self.actor_target_net = self.build_network(\n",
    "                input_size=observation_dim, **actor_kwargs)\n",
    "        self.critic_evaluate_net = self.build_network(\n",
    "                input_size=observation_action_dim, **critic_kwargs)\n",
    "        self.critic_target_net = self.build_network(\n",
    "                input_size=observation_action_dim, **critic_kwargs)\n",
    "        \n",
    "        self.update_target_net(self.actor_target_net,\n",
    "                self.actor_evaluate_net)\n",
    "        self.update_target_net(self.critic_target_net,\n",
    "                self.critic_evaluate_net)\n",
    "        \n",
    "    def update_target_net(self, target_net, evaluate_net,\n",
    "            learning_rate=1.):\n",
    "        target_weights = target_net.get_weights()\n",
    "        evaluate_weights = evaluate_net.get_weights()\n",
    "        average_weights = [(1. - learning_rate) * t + learning_rate * e\n",
    "                    for t, e in zip(target_weights, evaluate_weights)]\n",
    "        target_net.set_weights(average_weights)\n",
    "        \n",
    "    def build_network(self, input_size, hidden_sizes, output_size=1,\n",
    "            activation=tf.nn.relu, output_activation=None,\n",
    "            loss=tf.losses.mse, learning_rate=0.001):\n",
    "        model = keras.Sequential()\n",
    "        for layer, hidden_size in enumerate(hidden_sizes):\n",
    "            kwargs = {'input_shape' : (input_size,)} if layer == 0 else {}\n",
    "            model.add(keras.layers.Dense(units=hidden_size,\n",
    "                    activation=activation, **kwargs))\n",
    "        model.add(keras.layers.Dense(units=output_size,\n",
    "                activation=output_activation))\n",
    "        optimizer = tf.optimizers.Adam(learning_rate)\n",
    "        model.compile(optimizer=optimizer, loss=loss)\n",
    "        return model\n",
    "    \n",
    "    def decide(self, observation):\n",
    "        if self.explore and self.replayer.count < \\\n",
    "                self.replayer_initial_transitions:\n",
    "            return np.random.uniform(self.action_low, self.action_high)\n",
    "        \n",
    "        action = self.actor_evaluate_net.predict(\n",
    "                observation[np.newaxis])[0]\n",
    "        if self.explore:\n",
    "            noise = self.noise()\n",
    "            action = np.clip(action + noise, self.action_low, self.action_high)\n",
    "        return action\n",
    "    \n",
    "    def learn(self, observation, action, reward, next_observation, done):\n",
    "        self.replayer.store(observation, action, reward, next_observation,\n",
    "                done)\n",
    "        \n",
    "        if self.replayer.count >= self.replayer_initial_transitions:\n",
    "            if done:\n",
    "                self.noise.reset() # 为下一回合重置噪声过程\n",
    "\n",
    "            for batch in range(self.batches):\n",
    "                observations, actions, rewards, next_observations, \\\n",
    "                        dones = self.replayer.sample(self.batch_size)\n",
    "\n",
    "                # 训练执行者网络\n",
    "                observation_tensor = tf.convert_to_tensor(observations,\n",
    "                        dtype=tf.float32)\n",
    "                with tf.GradientTape() as tape:\n",
    "                    action_tensor = self.actor_evaluate_net(\n",
    "                            observation_tensor)\n",
    "                    input_tensor = tf.concat([observation_tensor,\n",
    "                            action_tensor], axis=1)\n",
    "                    q_tensor = self.critic_evaluate_net(input_tensor)\n",
    "                    loss_tensor = -tf.reduce_mean(q_tensor)\n",
    "                grad_tensors = tape.gradient(loss_tensor,\n",
    "                        self.actor_evaluate_net.variables)\n",
    "                self.actor_evaluate_net.optimizer.apply_gradients(zip(\n",
    "                        grad_tensors, self.actor_evaluate_net.variables))\n",
    "\n",
    "                # 训练评论者网络\n",
    "                next_actions = self.actor_target_net.predict(\n",
    "                        next_observations)\n",
    "                observation_actions = np.hstack([observations, actions])\n",
    "                next_observation_actions = np.hstack(\n",
    "                        [next_observations, next_actions])\n",
    "                next_qs = self.critic_target_net.predict(\n",
    "                        next_observation_actions)[:, 0]\n",
    "                targets = rewards + self.gamma * next_qs * (1. - dones)\n",
    "                self.critic_evaluate_net.fit(observation_actions, targets,\n",
    "                        verbose=0)\n",
    "\n",
    "                self.update_target_net(self.actor_target_net,\n",
    "                        self.actor_evaluate_net, self.net_learning_rate)\n",
    "                self.update_target_net(self.critic_target_net,\n",
    "                        self.critic_evaluate_net, self.net_learning_rate)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "i3gLq96hmyEC"
   },
   "outputs": [],
   "source": [
    "def play_qlearning(env, agent, train=False, render=False):\n",
    "    episode_reward = 0\n",
    "    observation = env.reset()\n",
    "    while True:\n",
    "        if render:\n",
    "            env.render()\n",
    "        action = agent.decide(observation)\n",
    "        next_observation, reward, done, _ = env.step(action)\n",
    "        episode_reward += reward\n",
    "        if train:\n",
    "            agent.learn(observation, action, reward, next_observation, done)\n",
    "        if done:\n",
    "            break\n",
    "        observation = next_observation\n",
    "    return episode_reward"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 367
    },
    "colab_type": "code",
    "id": "cL2gPsJimyEE",
    "outputId": "e8aa370d-1f00-4ac3-94b9-ccc923544a5e",
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "平均回合奖励 = -39268.43160455029 / 100 = -392.68431604550295\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "actor_kwargs = {'hidden_sizes' : [32, 64], 'learning_rate' : 0.0001}\n",
    "critic_kwargs = {'hidden_sizes' : [64, 128], 'learning_rate' : 0.001}\n",
    "agent = DDPGAgent(env, actor_kwargs=actor_kwargs,\n",
    "        critic_kwargs=critic_kwargs)\n",
    "\n",
    "# 训练\n",
    "episodes = 100\n",
    "episode_rewards = []\n",
    "for episode in range(episodes):\n",
    "    episode_reward = play_qlearning(env, agent, train=True)\n",
    "    episode_rewards.append(episode_reward)\n",
    "plt.plot(episode_rewards)\n",
    "\n",
    "# 测试\n",
    "agent.explore = False # 取消探索\n",
    "episode_rewards = [play_qlearning(env, agent) for _ in range(100)]\n",
    "print('平均回合奖励 = {} / {} = {}'.format(sum(episode_rewards),\n",
    "        len(episode_rewards), np.mean(episode_rewards)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "双重延迟深度确定性策略梯度算法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {},
    "colab_type": "code",
    "id": "kcieY0EAmyEJ"
   },
   "outputs": [],
   "source": [
    "class TD3Agent(DDPGAgent):\n",
    "    def __init__(self, env, actor_kwargs, critic_kwargs,\n",
    "            replayer_capacity=100000, replayer_initial_transitions=10000,\n",
    "            gamma=0.99, batches=1, batch_size=64,\n",
    "            net_learning_rate=0.005, noise_scale=0.1, explore=True):\n",
    "        observation_dim = env.observation_space.shape[0]\n",
    "        action_dim = env.action_space.shape[0]\n",
    "        observation_action_dim = observation_dim + action_dim\n",
    "        self.action_low = env.action_space.low\n",
    "        self.action_high = env.action_space.high\n",
    "        self.gamma = gamma\n",
    "        self.net_learning_rate = net_learning_rate\n",
    "        self.explore = explore\n",
    "        \n",
    "        self.batches = batches\n",
    "        self.batch_size = batch_size\n",
    "        self.replayer = DQNReplayer(replayer_capacity)\n",
    "        self.replayer_initial_transitions = replayer_initial_transitions\n",
    "        \n",
    "        self.noise = OrnsteinUhlenbeckProcess(size=(action_dim,),\n",
    "                sigma=noise_scale)\n",
    "        self.noise.reset()\n",
    "        \n",
    "        self.actor_evaluate_net = self.build_network(\n",
    "                input_size=observation_dim, **actor_kwargs)\n",
    "        self.actor_target_net = self.build_network(\n",
    "                input_size=observation_dim, **actor_kwargs)\n",
    "        self.critic0_evaluate_net = self.build_network(\n",
    "                input_size=observation_action_dim, **critic_kwargs)\n",
    "        self.critic0_target_net = self.build_network(\n",
    "                input_size=observation_action_dim, **critic_kwargs)\n",
    "        self.critic1_evaluate_net = self.build_network(\n",
    "                input_size=observation_action_dim, **critic_kwargs)\n",
    "        self.critic1_target_net = self.build_network(\n",
    "                input_size=observation_action_dim, **critic_kwargs)\n",
    "        \n",
    "        self.update_target_net(self.actor_target_net,\n",
    "                self.actor_evaluate_net)\n",
    "        self.update_target_net(self.critic0_target_net,\n",
    "                self.critic0_evaluate_net)\n",
    "        self.update_target_net(self.critic1_target_net,\n",
    "                self.critic1_evaluate_net)\n",
    "        \n",
    "    \n",
    "    def learn(self, observation, action, reward, next_observation, done):\n",
    "        self.replayer.store(observation, action, reward, next_observation,\n",
    "                done)\n",
    "        \n",
    "        if self.replayer.count >= self.replayer_initial_transitions:\n",
    "            if done:\n",
    "                self.noise.reset()\n",
    "\n",
    "            for batch in range(self.batches):\n",
    "                observations, actions, rewards, next_observations, \\\n",
    "                        dones = self.replayer.sample(self.batch_size)\n",
    "\n",
    "                # 训练执行者\n",
    "                observation_tensor = tf.convert_to_tensor(observations,\n",
    "                        dtype=tf.float32)\n",
    "                with tf.GradientTape() as tape:\n",
    "                    action_tensor = self.actor_evaluate_net(\n",
    "                            observation_tensor)\n",
    "                    input_tensor = tf.concat([observation_tensor,\n",
    "                            action_tensor], axis=1)\n",
    "                    q_tensor = self.critic0_evaluate_net(input_tensor)\n",
    "                    loss_tensor = -tf.reduce_mean(q_tensor)\n",
    "                grad_tensors = tape.gradient(loss_tensor,\n",
    "                        self.actor_evaluate_net.variables)\n",
    "                self.actor_evaluate_net.optimizer.apply_gradients(zip(\n",
    "                        grad_tensors, self.actor_evaluate_net.variables))\n",
    "\n",
    "                # 训练评论者\n",
    "                next_actions = self.actor_target_net.predict(\n",
    "                        next_observations)\n",
    "                observation_actions = np.hstack([observations, actions])\n",
    "                next_observation_actions = np.hstack(\n",
    "                        [next_observations, next_actions])\n",
    "                next_q0s = self.critic0_target_net.predict(\n",
    "                        next_observation_actions)[:, 0]\n",
    "                next_q1s = self.critic1_target_net.predict(\n",
    "                        next_observation_actions)[:, 0]\n",
    "                next_qs = np.minimum(next_q0s, next_q1s)\n",
    "                targets = rewards + self.gamma * next_qs * (1. - dones)\n",
    "                self.critic0_evaluate_net.fit(observation_actions,\n",
    "                        targets[:, np.newaxis], verbose=0)\n",
    "                self.critic1_evaluate_net.fit(observation_actions,\n",
    "                        targets[:, np.newaxis], verbose=0)\n",
    "\n",
    "                self.update_target_net(self.actor_target_net,\n",
    "                        self.actor_evaluate_net, self.net_learning_rate)\n",
    "                self.update_target_net(self.critic0_target_net,\n",
    "                        self.critic0_evaluate_net, self.net_learning_rate)\n",
    "                self.update_target_net(self.critic1_target_net,\n",
    "                        self.critic1_evaluate_net, self.net_learning_rate)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 387
    },
    "colab_type": "code",
    "id": "N9RBNZo9myEM",
    "outputId": "8d043bfd-d75c-4a28-98be-0a5ceb981651",
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "平均回合奖励 = -42198.52866718139 / 100 = -421.98528667181404\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "actor_kwargs = {'hidden_sizes' : [32, 64], 'learning_rate' : 0.0001}\n",
    "critic_kwargs = {'hidden_sizes' : [64, 128], 'learning_rate' : 0.001}\n",
    "agent = TD3Agent(env, actor_kwargs=actor_kwargs,\n",
    "        critic_kwargs=critic_kwargs)\n",
    "\n",
    "# 训练\n",
    "episodes = 100\n",
    "episode_rewards = []\n",
    "for episode in range(episodes):\n",
    "    episode_reward = play_qlearning(env, agent, train=True)\n",
    "    episode_rewards.append(episode_reward)\n",
    "plt.plot(episode_rewards)\n",
    "\n",
    "# 测试\n",
    "agent.explore = False # 取消探索\n",
    "episode_rewards = [play_qlearning(env, agent) for _ in range(100)]\n",
    "print('平均回合奖励 = {} / {} = {}'.format(sum(episode_rewards),\n",
    "        len(episode_rewards), np.mean(episode_rewards)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "env.close()"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "collapsed_sections": [],
   "name": "Pendulum-v0.eager.201902032240.ipynb",
   "provenance": [],
   "version": "0.3.2"
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
